# -*- coding: utf-8 -*-
# $Id: parser.py 79 2010-02-18 15:25:44Z 4glitch $

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import threads
from datetime import datetime
import re

dow = '(Sun|Mon|Tue|Wed|Thu|Fri|Sat)'
mon = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)'
yp = '[2-9][0-9]{3}'


time_re = re.compile("(%s )?%s {1,2}[0-9]{1,2} ([0-9]{2}:){2}[0-9]{2}( %s)?" %
                     (dow, mon, yp))
year = datetime.today().year

from twisted.python import log


class SQLPipe(DatagramProtocol):
    
    def __init__(self, factory):
        self.factory = factory
    
    def datagramReceived(self, msg, (host, port)):
        
        values = self._split_datagram(msg) # this may be done with deferred
        if values: # can't decide how to resolve here
            values.update({'host': host})
            threads.deferToThread(self.factory.insertEntry, values)
            
    
    def _split_datagram(self, msg):
        if msg[0] == '<':
            next = msg.find('>', 1, 5)
            if next > 0:
                now = datetime.now()
                pri, msg = int(msg[1:next]), msg[next+1:]
                
                match = time_re.match(msg)
                if match and match.start() == 0:
                    next = match.end()
                    time, msg = msg[:next], msg[next+1:]
                    
                    if re.match(dow, time): time = time.split(' ', 1)[1]
                    if not re.match('.*' + yp, time): time += ' ' + str(year)
                    time = datetime.strptime(time, '%b %d %H:%M:%S %Y')
                else:
                    time = now
                
                next = msg.find(':')
                pid = None
                # is it really no whitespace
                if next > 0 and msg[:next].find(' ') == -1:
                    program, msg = msg[:next], msg[next+1:].strip()
                    try:
                        program, pid = program.split('[')
                        pid, rest = pid.split(']')
                        if rest != '': raise ValueError
                    except ValueError:
                        pass
                else:
                    program = ''
            
            return {"severity": pri & 7,
                    "facility": (pri & 248) >> 3,
                    "time": time,
                    "program": program,
                    "pid": pid,
                    "message": msg}
        else:
            return None
